package com.smartinput.device.application.service

import com.mensanyun.kotool.extension.ifNullThen
import com.mensanyun.kotool.util.UlidUtil
import com.smartinput.device.application.dto.DeviceInfo
import com.smartinput.device.application.dto.DeviceRegisterRequest
import com.smartinput.device.application.dto.DeviceRegisterResponse
import com.smartinput.device.domain.model.Device
import com.smartinput.device.domain.repository.DeviceRepository
import com.smartinput.device.query.service.DeviceQueryService
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime

@Transactional
@Service
class DeviceService(
    private val deviceRepository: DeviceRepository,
    private val deviceQueryService: DeviceQueryService,
    private val deviceStatusManager: DeviceStatusManager
) {
    
    private val logger = LoggerFactory.getLogger(DeviceService::class.java)

    fun registerDevice(request: DeviceRegisterRequest): DeviceRegisterResponse {
        // 检查设备ID是否已存在
        val existingDevice = deviceRepository.findByDeviceId(request.deviceId)
        if (existingDevice != null) {
            logger.warn("设备注册失败：设备ID已存在 - deviceId=${request.deviceId}, existingUserId=${existingDevice.userId}")
            throw IllegalArgumentException("设备ID已存在")
        }

        // 获取当前登录用户ID
        val currentUserId = getCurrentUserId()
        logger.debug("设备注册，当前用户ID: $currentUserId, 请求用户ID: ${request.userId}")

        // 确保有有效的用户ID
        val userId = currentUserId ?: request.userId
        if (userId.isNullOrBlank()) {
            throw IllegalArgumentException("无法获取有效的用户ID，请确保用户已登录")
        }

        // 创建新设备，使用有效的用户ID
        val device = Device(
            uid = UlidUtil.generate(),
            deviceId = request.deviceId, // 使用插件传递的 deviceId
            userId = userId, // 使用有效的用户ID
            deviceName = request.deviceName,
            deviceType = request.deviceType,
            enabled = true,
            createdAt = LocalDateTime.now(),
        )

        val savedDevice = deviceRepository.save(device)
        logger.info("设备注册成功: deviceId=${savedDevice.deviceId}, userId=${savedDevice.userId}")

        return DeviceRegisterResponse(
            deviceId = savedDevice.deviceId, deviceName = savedDevice.deviceName ?: ""
        )
    }

    fun getUserDevices(userId: String): List<DeviceInfo> {
        val devices = deviceQueryService.findByUserId(userId)
        return devices.map { device ->
            // 使用设备状态管理器获取实时状态
            val isWebSocketOnline = deviceStatusManager.isDeviceOnline(device.deviceId)
            
            // 如果WebSocket状态与数据库状态不一致，更新数据库
            if (device.online != isWebSocketOnline) {
                logger.debug("设备状态不一致，更新数据库状态: ${device.deviceId} (数据库: ${device.online}, WebSocket: $isWebSocketOnline)")
                try {
                    updateDeviceStatus(device.deviceId, isWebSocketOnline, device.socketId)
                } catch (e: Exception) {
                    logger.error("更新设备状态失败: ${device.deviceId}", e)
                }
            }
            
            DeviceInfo(
                deviceId = device.deviceId,
                deviceType = device.deviceType,
                deviceName = device.deviceName ?: "",
                online = isWebSocketOnline, // 使用实时状态
                lastHeartbeat = device.lastHeartbeat?.toString()
            )
        }
    }

//    fun getDevicesByUserName(userName: String){
//        val devices = deviceRepository.findByUserName(userName)
//
//    }

    @Transactional
    fun updateDeviceStatus(deviceId: String, online: Boolean, socketId: String?) {
        var retryCount = 0
        val maxRetries = 3
        
        while (retryCount < maxRetries) {
            try {
                val device = deviceRepository.findByDeviceId(deviceId) ?: throw IllegalArgumentException("设备不存在")
                device.updateStatus(online, socketId)
                deviceRepository.save(device)
                logger.debug("设备状态更新成功: deviceId=$deviceId, online=$online")
                return
            } catch (e: Exception) {
                retryCount++
                if (retryCount >= maxRetries) {
                    logger.error("更新设备状态失败，已重试${maxRetries}次: deviceId=$deviceId, error=${e.message}")
                    throw e
                }
                logger.warn("更新设备状态失败，正在重试 ($retryCount/$maxRetries): deviceId=$deviceId, error=${e.message}")
                Thread.sleep((100 * retryCount).toLong()) // 递增延迟
            }
        }
    }

    @Transactional
    fun updateLastHeartbeat(deviceId: String) {
        var retryCount = 0
        val maxRetries = 3
        
        while (retryCount < maxRetries) {
            try {
                val device = deviceRepository.findByDeviceId(deviceId) ?: throw IllegalArgumentException("设备不存在")
                device.updateHeartbeat()
                deviceRepository.save(device)
                logger.debug("设备心跳更新成功: deviceId=$deviceId")
                return
            } catch (e: Exception) {
                retryCount++
                if (retryCount >= maxRetries) {
                    logger.error("更新设备心跳失败，已重试${maxRetries}次: deviceId=$deviceId, error=${e.message}")
                    throw e
                }
                logger.warn("更新设备心跳失败，正在重试 ($retryCount/$maxRetries): deviceId=$deviceId, error=${e.message}")
                Thread.sleep((100 * retryCount).toLong()) // 递增延迟
            }
        }
    }

    fun registerIfNecessary(deviceId: String, deviceType: String, deviceName: String, userId: String?) {
        val existingDevice = this.deviceRepository.findByDeviceId(deviceId)
        if (existingDevice != null) {
            logger.debug("设备已存在，跳过注册: deviceId=$deviceId, existingUserId=${existingDevice.userId}")
            return
        }
        
        // 直接创建设备，不通过registerDevice方法
        val device = Device(
            uid = com.mensanyun.kotool.util.UlidUtil.generate(),
            deviceId = deviceId,
            userId = userId,
            deviceName = deviceName,
            deviceType = deviceType,
            enabled = true,
            createdAt = java.time.LocalDateTime.now(),
        )
        
        val savedDevice = deviceRepository.save(device)
        logger.info("设备注册成功: deviceId=${savedDevice.deviceId}, userId=${savedDevice.userId}")
    }

    fun validateDeviceOwnership(deviceId: String, userId: String): Boolean {
        val device = deviceQueryService.findByDeviceId(deviceId)
        return device?.userId == userId
    }

    fun getDeviceBySocketId(socketId: String): Device? {
        val deviceEntry = deviceQueryService.findBySocketId(socketId)
        return deviceEntry?.let { entry ->
            deviceRepository.findByDeviceId(entry.deviceId)
        }
    }

    fun getDeviceByDeviceId(deviceId: String): Device? {
        return deviceRepository.findByDeviceId(deviceId)
    }

    /**
     * 将匿名设备关联到指定用户
     */
    fun claimAnonymousDevice(deviceId: String, userId: String): Boolean {
        val device = deviceRepository.findByDeviceId(deviceId)
        if (device == null) {
            throw IllegalArgumentException("设备不存在")
        }

        if (device.userId != null) {
            throw IllegalArgumentException("设备已被其他用户关联")
        }

        // 更新设备用户ID
        device.bindUser(userId)
        deviceRepository.save(device)

        logger.info("匿名设备已关联到用户: deviceId=$deviceId, userId=$userId")
        return true
    }

    /**
     * 获取用户的所有设备（包括匿名设备）
     */
    fun getUserDevicesIncludingAnonymous(userId: String): List<DeviceInfo> {
        val userDevices = deviceQueryService.findByUserId(userId)
        val anonymousDevices = deviceQueryService.findAnonymousDevices()

        val allDevices = userDevices + anonymousDevices
        return allDevices.map { device ->
            DeviceInfo(
                deviceId = device.deviceId,
                deviceName = device.deviceName ?: "",
                online = device.online,
                deviceType = device.deviceType,
                lastHeartbeat = device.lastHeartbeat?.toString()
            )
        }
    }

    /**
     * 获取在线设备（包括匿名设备）
     */
    fun getOnlineDevices(userId: String): List<DeviceInfo> {
        val userDevices = deviceQueryService.findOnlineDevicesByUserId(userId)
        val anonymousDevices = deviceQueryService.findOnlineAnonymousDevices()

        val allOnlineDevices = userDevices + anonymousDevices
        return allOnlineDevices.map { device ->
            DeviceInfo(
                deviceId = device.deviceId,
                deviceName = device.deviceName ?: "",
                online = device.online,
                deviceType = device.deviceType,
                lastHeartbeat = device.lastHeartbeat?.toString()
            )
        }
    }


    private fun getCurrentUserId(): String? {
        return try {
            val authentication =
                org.springframework.security.core.context.SecurityContextHolder.getContext().authentication
            if (authentication != null && authentication.isAuthenticated && authentication.name != null) {
                authentication.name
            } else {
                null
            }
        } catch (e: Exception) {
            logger.error("获取当前用户ID失败: ${e.message}")
            null
        }
    }

    fun heartbeat(deviceId: String) {
        val device = deviceRepository.findByDeviceId(deviceId) ?: throw IllegalArgumentException("设备不存在")
        device.updateHeartbeat()
        device.updateStatus(true, device.socketId)
        deviceRepository.save(device)
    }
}